/**
 * @file 页面缓存组件
 * @date 2025/11/20 14:32:16
 * @author lyqjob@yeah.net
 */

import { useEffect, useMemo, useRef, useState } from 'react'
import { useLocation, useOutlet } from 'react-router-dom'

const store = new Map()
const order = []
let limit = 12


// 移除缓存
const removeKey = (k) => {
    if (!store.has(k)) return
    store.delete(k)
    const idx = order.indexOf(k)
    if (idx >= 0) order.splice(idx, 1)
}

// 缓存组件
const KeepAliveOutlet = () => {
    const location = useLocation()
    const outlet = useOutlet()
    const activeKey = location.pathname
    const [, setTick] = useState(0)
    const activeRef = useRef(activeKey)
    activeRef.current = activeKey

    if (outlet) {
        if (!store.has(activeKey)) {
            store.set(activeKey, outlet)
            order.push(activeKey)
            if (store.size > limit) {
                const dropKey = order[0]
                if (dropKey && dropKey !== activeKey) removeKey(dropKey)
            }
        } else {
            store.set(activeKey, outlet)
        }
    }

    useEffect(() => {
        const onDrop = (e) => {
            const k = e?.detail?.key
            if (!k) return
            removeKey(k)
            if (k === activeRef.current) setTick((v) => v + 1)
        }
        const onClear = () => {
            store.clear()
            order.splice(0, order.length)
            setTick((v) => v + 1)
        }
        window.addEventListener('keepalive:drop', onDrop)
        window.addEventListener('keepalive:clear', onClear)
        return () => {
            window.removeEventListener('keepalive:drop', onDrop)
            window.removeEventListener('keepalive:clear', onClear)
        }
    }, [])

    const nodes = useMemo(() => {
        const list = []
        for (const [k, el] of store.entries()) {
            list.push(
                <div key={k} style={{ display: k === activeKey ? 'block' : 'none', height: '100%' }}>
                    {el}
                </div>
            )
        }
        return list
    }, [activeKey, store.size])

    return nodes
}

export default KeepAliveOutlet